#pragma once

#include <string>
#include <stdint.h>

#include "EventLoop.h"
#include "Socket.h"
#include "SocketError.hpp"
#include "ChannelDelegate.h"

namespace nio {

	class AddressResolver;

	class ClientChannel : public Selectable
	{
	private:
		Socket* socket = nullptr;
		ChannelDelegate* delegate = nullptr;
		std::shared_ptr<Task> connectTimeout = nullptr;
		std::shared_ptr<AddressResolver> resolver = nullptr;

		std::string writeBuf;
		ChannelStatus status = ChannelStatus::idle;
	public:
		EventLoop* eventLoop = nullptr;
	public:
		ClientChannel(ChannelDelegate* delegate);
		ClientChannel(ChannelDelegate* delegate, EventLoop* eventLoop, Socket* socket);
		virtual ~ClientChannel();

		void connect(std::string host, int port, int64_t timeout = 10000);
		void disconnect();
		void write(std::string& data);

		ChannelStatus getStatus() { return status; }
		void setStatus(ChannelStatus status) { this->status = status; }

		SocketAddress getLocalAddress();
		SocketAddress getRemoteAddress();
	public:
		virtual SOCKET getFD();
		virtual void onEvents(int events);

	private:
		void onConnect();
		void onDisconnect(SocketError* error);
		void onWritable();
		void onReadable();

		void addWritable();
		void removeWritable();
	};

}